Skip to content

docs: explain realistic OIDC sandbox tokens#487

Merged
DhruvPareek merged 1 commit into
mainfrom
dp/docs-realistic-oidc-sandbox
May 28, 2026
Merged

docs: explain realistic OIDC sandbox tokens#487
DhruvPareek merged 1 commit into
mainfrom
dp/docs-realistic-oidc-sandbox

Conversation

@DhruvPareek
Copy link
Copy Markdown
Contributor

@DhruvPareek DhruvPareek commented May 21, 2026

Summary

  • Update Global Accounts sandbox docs to explain that OAuth no longer uses the fixed sandbox-valid-oidc-token value.
  • Document the sandbox OIDC token requirements: JWT-shaped token, supported issuer, aud/sub, fresh iat/exp, stored iss/aud/sub identity matching, and nonce = sha256(clientPublicKey) on verify.
  • Clarify that sandbox can use supported-provider ID tokens, while unsigned JWT-shaped tokens are only a sandbox test-token option.
  • Update the auth OpenAPI descriptions and rebuild the bundled openapi.yaml and mintlify/openapi.yaml.

Stack

Context

This matches the Grid behavior from the OIDC auth-method identity stack:

  • dp/grid-oidc-auth-method-identity
  • dp/grid-realistic-oidc-sandbox
  • dp/grid-verify-oauth-oidc-identity

The important customer-facing change is that sandbox no longer accepts a fixed OAuth magic token. It validates the same identity/freshness shape integrators need in production, while still skipping real IdP signature verification in the mock Turnkey path.

Test Plan

  • npm run lint

@vercel
Copy link
Copy Markdown

vercel Bot commented May 21, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
grid-flow-builder Ready Ready Preview, Comment May 28, 2026 9:42pm

Request Review

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 21, 2026

✱ Stainless preview builds for grid

This PR will update the grid SDKs with the following commit messages.

cli

chore(internal): regenerate SDK with no functional changes

csharp

docs(api): update OAuth credential verification documentation in auth

go

docs(api): clarify OAuth token verification in authcredential

kotlin

docs(api): update OAuth credential verification documentation

openapi

docs(api): clarify OAuth token validation requirements for auth credentials

php

docs(api): update OAuth credential verification documentation

python

docs(api): clarify OAuth token requirements in credentials methods

ruby

docs(api): update oidc_token documentation in OAuth credential models

typescript

docs(api): update OAuth token requirements in auth credentials
⚠️ grid-openapi studio · code

Your SDK build had at least one warning diagnostic.
generate ✅

⚠️ grid-ruby studio · code

Your SDK build had a failure in the lint CI job, which is a regression from the base state.
generate ⚠️build ✅lint ❗test ✅

⚠️ grid-kotlin studio · code

Your SDK build had a failure in the test CI job, which is a regression from the base state.
generate ✅build ✅lint ✅test ❗

⚠️ grid-typescript studio · code

Your SDK build had a failure in the build CI job, which is a regression from the base state.
generate ✅build ❗lint ❗test ❗

⚠️ grid-python studio · code

Your SDK build had at least one warning diagnostic.
generate ✅build ✅lint ✅test ✅

pip install https://pkg.stainless.com/s/grid-python/c9afe7d65132317f72af3ed0223dd071157b1d61/grid-0.0.1-py3-none-any.whl
grid-csharp studio · code

generate ❗build ❗lint ❗test ⏳

⚠️ grid-go studio · code

Your SDK build had a failure in the lint CI job, which is a regression from the base state.
generate ❗build ✅lint ❗test ❗

go get github.com/stainless-sdks/grid-go@12a840bb6d910aa542e92d2b8f1395fece728fda
⚠️ grid-php studio · code

Your SDK build had a failure in the lint CI job, which is a regression from the base state.
generate ❗lint ❗test ✅

⚠️ grid-cli studio · code

Your SDK build had a failure in the test CI job, which is a regression from the base state.
generate ⚠️build ⏭️lint ⏭️test ❗

⏳ These are partial results; builds are still running.


This comment is auto-generated by GitHub Actions and is automatically kept up to date as you push.
If you push custom code to the preview branch, re-run this workflow to update the comment.
Last updated: 2026-05-28 21:54:33 UTC

@DhruvPareek DhruvPareek force-pushed the dp/docs-realistic-oidc-sandbox branch from 2c94a1c to 907c2cd Compare May 21, 2026 22:02
@DhruvPareek DhruvPareek changed the base branch from docs-auth-pdf-endpoint-followups to main May 21, 2026 22:02
Copy link
Copy Markdown
Contributor Author

DhruvPareek commented May 21, 2026

@DhruvPareek DhruvPareek marked this pull request as ready for review May 21, 2026 22:08
@DhruvPareek DhruvPareek requested a review from pengying May 21, 2026 22:08
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 21, 2026

Greptile Summary

This PR updates the Global Accounts sandbox and OpenAPI docs to replace the old fixed sandbox-valid-oidc-token magic value with the new realistic OIDC token model, where the sandbox validates JWT structure, claim freshness, credential identity, and (on verify) a nonce = sha256(clientPublicKey) binding — while skipping real IdP signature verification.

  • Sandbox testing page & magic snippet — rewrites the OAuth section to list all required claims for both create and verify, adds a copyable Node.js snippet that generates a compliant sandbox JWT with the correct nonce, and deprecates the old literal token.
  • OpenAPI source schemas and path files — updates oidcToken descriptions in OauthCredentialCreateRequestFields, OauthCredentialVerifyRequestFields, and both auth path files to document the production-vs-sandbox split and the new identity/nonce checks; regenerated bundles (openapi.yaml, mintlify/openapi.yaml) are included.
  • Authentication snippet — adds identity-matching prose and a <Note> callout pointing to the sandbox testing page.

Confidence Score: 3/5

Docs-only change; no application logic is touched. The main risk is integrators picking up the wrong example shape from the spec.

The OpenAPI example JWT for OauthCredentialVerifyRequestFields has no nonce field, directly contradicting the description text that sandbox requires one. An integrator who uses this schema example as a starting point in sandbox will receive a 401 nonce failure with no clear pointer to the cause. The nonce hash encoding (hex vs. base64) is also undocumented in prose — only visible in the Node.js code block — which could trip up developers writing equivalent code in other languages. Everything else in the PR is accurate and internally consistent.

openapi/components/schemas/auth/OauthCredentialVerifyRequestFields.yaml — the verify example JWT needs a nonce claim to match the documented sandbox requirement

Important Files Changed

Filename Overview
mintlify/snippets/sandbox-global-account-magic.mdx Core sandbox docs rewrite — replaces fixed magic token with JWT-shaped OIDC requirements and adds a Node.js code example; nonce hash encoding is unspecified in prose
openapi/components/schemas/auth/OauthCredentialVerifyRequestFields.yaml Updated oidcToken description adds sandbox nonce requirement; the static example JWT has no nonce claim, which contradicts the sandbox requirement for verify
openapi/components/schemas/auth/OauthCredentialCreateRequestFields.yaml Updated oidcToken description to document production vs sandbox validation rules; changes are accurate and no nonce is required here
openapi/paths/auth/auth_credentials_{id}_verify.yaml Operation description and 401 response updated to reflect identity/nonce checks; the OAuth verify example request still uses the non-nonce JWT example value
openapi/paths/auth/auth_credentials.yaml 400 and 401 response descriptions refined to clarify OAUTH-specific error cases; changes are accurate
mintlify/snippets/global-accounts/authentication.mdx Added identity-matching prose and a sandbox Note callout with a link to the sandbox testing page; clear and accurate
mintlify/global-accounts/platform-tools/sandbox-testing.mdx Minor description updates to reflect OIDC flow change; accurate
mintlify/global-accounts/index.mdx One-line card description update to reflect new OIDC sandbox behavior; accurate

Sequence Diagram

sequenceDiagram
    participant Dev as Integrator
    participant SB as Grid Sandbox

    Note over Dev,SB: OAuth Credential Registration (POST /auth/credentials)
    Dev->>Dev: "Generate JWT with iss, aud, sub, iat, exp (signature = dummy value)"
    Dev->>SB: "POST /auth/credentials { type: OAUTH, oidcToken }"
    SB->>SB: Validate JWT structure and iss support
    SB->>SB: Verify iat freshness (60s window)
    SB->>SB: Store iss + aud + sub as credential identity
    SB-->>Dev: "200 { id: AuthMethod:... }"

    Note over Dev,SB: OAuth Credential Verification (POST /auth/credentials/{id}/verify)
    Dev->>Dev: Generate ephemeral P-256 key pair
    Dev->>Dev: "Compute nonce = sha256(clientPublicKey) hex-encoded"
    Dev->>Dev: Generate fresh JWT with iss, aud, sub, iat, exp, nonce
    Dev->>SB: "POST /auth/credentials/{id}/verify { type: OAUTH, oidcToken, clientPublicKey }"
    SB->>SB: Validate JWT structure and iss support
    SB->>SB: Verify iat freshness (60s window)
    SB->>SB: Match iss + aud + sub against stored credential identity
    SB->>SB: "Verify nonce == sha256(clientPublicKey)"
    SB->>SB: Encrypt session signing key to clientPublicKey (HPKE)
    SB-->>Dev: "200 { encryptedSessionSigningKey, expiresAt }"
Loading

Fix All in Claude Code

Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
mintlify/snippets/sandbox-global-account-magic.mdx:68
**`nonce` hash encoding not specified — developers not using the Node.js example may compute it incorrectly**

The prose says `nonce` must equal `sha256(clientPublicKey)` but doesn't say the output is hex-encoded. The code example uses `.digest("hex")`, producing a lowercase hex string. A developer writing a Python or Go integration might reach for base64 or raw bytes instead, producing a nonce the backend won't match, and getting a 401 with no obvious pointer to the encoding mismatch. Specifying "(hex-encoded)" inline removes the ambiguity.

```suggestion
Grid stores the OAuth credential's registered identity from `iss`, `aud`, and `sub`. On `POST /auth/credentials/{id}/verify`, the fresh `oidcToken` must carry the same `iss`, `aud`, and `sub` as the credential being verified. It must also include `nonce` equal to `sha256(clientPublicKey)` (hex-encoded lowercase), where `clientPublicKey` is the exact hex public key sent in the verify request.
```

### Issue 2 of 2
openapi/components/schemas/auth/OauthCredentialVerifyRequestFields.yaml:24
**Verify example JWT is missing the `nonce` claim now required in sandbox**

The static `example` value shared between create and verify schemas has no `nonce` field in its payload. The description directly above it states that sandbox requires `nonce = sha256(clientPublicKey)` for verify. An integrator who models their token on this example and tests in sandbox will immediately get a 401 nonce-mismatch error with no obvious clue why, since the example shape itself passes no nonce. The same example is intentionally correct for the create operation (where nonce is not required), but a verify-specific example — or a note on the example — is needed to avoid this mismatch.

Reviews (1): Last reviewed commit: "docs: explain realistic OIDC sandbox tok..." | Re-trigger Greptile

- `iat`: a numeric issued-at timestamp no more than 60 seconds before the request, with 5 seconds of clock skew allowed
- `exp`: a numeric expiration timestamp later than the request time

Grid stores the OAuth credential's registered identity from `iss`, `aud`, and `sub`. On `POST /auth/credentials/{id}/verify`, the fresh `oidcToken` must carry the same `iss`, `aud`, and `sub` as the credential being verified. It must also include `nonce` equal to `sha256(clientPublicKey)`, where `clientPublicKey` is the exact hex public key sent in the verify request.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 nonce hash encoding not specified — developers not using the Node.js example may compute it incorrectly

The prose says nonce must equal sha256(clientPublicKey) but doesn't say the output is hex-encoded. The code example uses .digest("hex"), producing a lowercase hex string. A developer writing a Python or Go integration might reach for base64 or raw bytes instead, producing a nonce the backend won't match, and getting a 401 with no obvious pointer to the encoding mismatch. Specifying "(hex-encoded)" inline removes the ambiguity.

Suggested change
Grid stores the OAuth credential's registered identity from `iss`, `aud`, and `sub`. On `POST /auth/credentials/{id}/verify`, the fresh `oidcToken` must carry the same `iss`, `aud`, and `sub` as the credential being verified. It must also include `nonce` equal to `sha256(clientPublicKey)`, where `clientPublicKey` is the exact hex public key sent in the verify request.
Grid stores the OAuth credential's registered identity from `iss`, `aud`, and `sub`. On `POST /auth/credentials/{id}/verify`, the fresh `oidcToken` must carry the same `iss`, `aud`, and `sub` as the credential being verified. It must also include `nonce` equal to `sha256(clientPublicKey)` (hex-encoded lowercase), where `clientPublicKey` is the exact hex public key sent in the verify request.
Prompt To Fix With AI
This is a comment left during a code review.
Path: mintlify/snippets/sandbox-global-account-magic.mdx
Line: 68

Comment:
**`nonce` hash encoding not specified — developers not using the Node.js example may compute it incorrectly**

The prose says `nonce` must equal `sha256(clientPublicKey)` but doesn't say the output is hex-encoded. The code example uses `.digest("hex")`, producing a lowercase hex string. A developer writing a Python or Go integration might reach for base64 or raw bytes instead, producing a nonce the backend won't match, and getting a 401 with no obvious pointer to the encoding mismatch. Specifying "(hex-encoded)" inline removes the ambiguity.

```suggestion
Grid stores the OAuth credential's registered identity from `iss`, `aud`, and `sub`. On `POST /auth/credentials/{id}/verify`, the fresh `oidcToken` must carry the same `iss`, `aud`, and `sub` as the credential being verified. It must also include `nonce` equal to `sha256(clientPublicKey)` (hex-encoded lowercase), where `clientPublicKey` is the exact hex public key sent in the verify request.
```

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code

be JWT-shaped with supported `iss`, non-empty `aud` and `sub`, numeric
`iat` and `exp`, and a `nonce` equal to `sha256(clientPublicKey)`, but
the signature segment may be a dummy value.
example: eyJhbGciOiJSUzI1NiIsImtpZCI6ImFiYzEyMyIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJzdWIiOiIxMTIyMzM0NDU1IiwiYXVkIjoiMTIzNDU2Ny5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsImVtYWlsIjoidXNlckBleGFtcGxlLmNvbSIsImlhdCI6MTc0NjczNjUwOSwiZXhwIjoxNzQ2NzQwMTA5fQ.signature
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Verify example JWT is missing the nonce claim now required in sandbox

The static example value shared between create and verify schemas has no nonce field in its payload. The description directly above it states that sandbox requires nonce = sha256(clientPublicKey) for verify. An integrator who models their token on this example and tests in sandbox will immediately get a 401 nonce-mismatch error with no obvious clue why, since the example shape itself passes no nonce. The same example is intentionally correct for the create operation (where nonce is not required), but a verify-specific example — or a note on the example — is needed to avoid this mismatch.

Prompt To Fix With AI
This is a comment left during a code review.
Path: openapi/components/schemas/auth/OauthCredentialVerifyRequestFields.yaml
Line: 24

Comment:
**Verify example JWT is missing the `nonce` claim now required in sandbox**

The static `example` value shared between create and verify schemas has no `nonce` field in its payload. The description directly above it states that sandbox requires `nonce = sha256(clientPublicKey)` for verify. An integrator who models their token on this example and tests in sandbox will immediately get a 401 nonce-mismatch error with no obvious clue why, since the example shape itself passes no nonce. The same example is intentionally correct for the create operation (where nonce is not required), but a verify-specific example — or a note on the example — is needed to avoid this mismatch.

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code

pengying
pengying previously approved these changes May 22, 2026
@DhruvPareek DhruvPareek changed the base branch from main to graphite-base/487 May 26, 2026 19:51
@DhruvPareek DhruvPareek force-pushed the dp/docs-realistic-oidc-sandbox branch from 907c2cd to 8983815 Compare May 26, 2026 19:51
@DhruvPareek DhruvPareek changed the base branch from graphite-base/487 to docs-auth-pdf-endpoint-followups May 26, 2026 19:51
@DhruvPareek DhruvPareek force-pushed the dp/docs-realistic-oidc-sandbox branch from 8983815 to a5b170b Compare May 26, 2026 21:06
@DhruvPareek DhruvPareek force-pushed the docs-auth-pdf-endpoint-followups branch from 5078263 to 07d5597 Compare May 26, 2026 21:06
@DhruvPareek DhruvPareek force-pushed the docs-auth-pdf-endpoint-followups branch from 07d5597 to 75cb985 Compare May 28, 2026 20:46
@DhruvPareek DhruvPareek force-pushed the dp/docs-realistic-oidc-sandbox branch from a5b170b to 847a4c3 Compare May 28, 2026 20:47
carsonp6
carsonp6 previously approved these changes May 28, 2026
@DhruvPareek DhruvPareek force-pushed the docs-auth-pdf-endpoint-followups branch from 75cb985 to d977c6d Compare May 28, 2026 21:21
@DhruvPareek DhruvPareek force-pushed the dp/docs-realistic-oidc-sandbox branch from 847a4c3 to af17727 Compare May 28, 2026 21:21
Copy link
Copy Markdown

@restamp-bot restamp-bot Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

af17727 is a pure rebase onto d977c6d. Approving based on @carsonp6's previous approval of 847a4c3.

@DhruvPareek DhruvPareek force-pushed the docs-auth-pdf-endpoint-followups branch 2 times, most recently from 3a8653f to 6cf147f Compare May 28, 2026 21:37
@DhruvPareek DhruvPareek force-pushed the dp/docs-realistic-oidc-sandbox branch from af17727 to 1ab5468 Compare May 28, 2026 21:37
Copy link
Copy Markdown

@restamp-bot restamp-bot Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1ab5468 is a pure rebase onto 6cf147f. Approving based on @carsonp6's previous approval of 847a4c3.

@DhruvPareek DhruvPareek changed the base branch from docs-auth-pdf-endpoint-followups to graphite-base/487 May 28, 2026 21:41
Copy link
Copy Markdown

@restamp-bot restamp-bot Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1ab5468 is a pure rebase onto 6cf147f. Approving based on @carsonp6's previous approval of 847a4c3.

@DhruvPareek DhruvPareek force-pushed the dp/docs-realistic-oidc-sandbox branch from 1ab5468 to cc31f2e Compare May 28, 2026 21:41
Copy link
Copy Markdown

@restamp-bot restamp-bot Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc31f2e is a pure rebase onto 21a8172. Approving based on @carsonp6's previous approval of 847a4c3.

restamp-bot[bot]
restamp-bot Bot previously approved these changes May 28, 2026
Copy link
Copy Markdown

@restamp-bot restamp-bot Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc31f2e is a pure rebase onto 21a8172. Approving based on @carsonp6's previous approval of 847a4c3.

@graphite-app graphite-app Bot changed the base branch from graphite-base/487 to main May 28, 2026 21:42
@graphite-app graphite-app Bot dismissed stale reviews from restamp-bot[bot], carsonp6, and pengying May 28, 2026 21:42

The base branch was changed.

@DhruvPareek DhruvPareek force-pushed the dp/docs-realistic-oidc-sandbox branch from cc31f2e to ec0391c Compare May 28, 2026 21:42
Copy link
Copy Markdown

@restamp-bot restamp-bot Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc31f2e is a pure rebase onto 21a8172. Approving based on @carsonp6's previous approval of 847a4c3.

Copy link
Copy Markdown

@restamp-bot restamp-bot Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ec0391c is a pure rebase onto 21a8172. Approving based on @carsonp6's previous approval of 847a4c3.

@DhruvPareek DhruvPareek merged commit 0047de2 into main May 28, 2026
7 of 8 checks passed
@DhruvPareek DhruvPareek deleted the dp/docs-realistic-oidc-sandbox branch May 28, 2026 21:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants